#include "ueq_fifo.h"

void ueq_fifo_test_byte_ops(int buffer_size)
{
    UeqFifo cb;
    BYTE buffer[8];
    BYTE data = 0;
    BYTE i = 0;
    BYTE j = 0;

    UEQ_ASSERT((buffer_size >= 2) && (buffer_size <= 8));

    /* Init test  */
    ueq_fifo_init(&cb, buffer, buffer_size);
    UEQ_ASSERT(ueq_fifo_is_empty(&cb));
    UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);

    /* Push back & pop front test - one element */
    for (i = 0; i < buffer_size; ++i)
    {
        ueq_fifo_push_back(&cb, i);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
        if (buffer_size == 2)
        {
            UEQ_ASSERT(ueq_fifo_is_full(&cb));
        }
        else
        {
            UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
        }

        data = ueq_fifo_pop_front(&cb);
        UEQ_ASSERT(data == i);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb));
        UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
    }

    /*  Push back & pop front test - make buffer full */
    for (i = 0; i < buffer_size; ++i)
    {
        for (j = 0; j < buffer_size - 2; ++j)
        {
            ueq_fifo_push_back(&cb, j);
            UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
            UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
        }

        ueq_fifo_push_back(&cb, buffer_size - 2);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
        UEQ_ASSERT(ueq_fifo_is_full(&cb));

        for (j = 0; j < buffer_size - 2; ++j)
        {
            data = ueq_fifo_pop_front(&cb);
            UEQ_ASSERT(data == j);
            UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
            UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
        }

        data = ueq_fifo_pop_front(&cb);
        UEQ_ASSERT(data == buffer_size - 2);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb));
        UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
    }

    /* Reset test */
    ueq_fifo_reset(&cb);
    UEQ_ASSERT(ueq_fifo_is_empty(&cb));
    UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
}

void ueq_fifo_test_memory_block_ops(int buffer_size)
{
    UeqFifo cb;
    BYTE buffer[8];
    BYTE data = 0;
    BYTE in[7] = {0, 1, 2, 3, 4, 5, 6};
    BYTE out[7];
    BOOL result = FALSE;
    BYTE i = 0;
    BYTE j = 0;

    UEQ_ASSERT((buffer_size >= 7) && (buffer_size <= 8));

    /*  Init test
        start:  []
        end:    [........]
    */
    ueq_fifo_init(&cb, buffer, buffer_size);
    UEQ_ASSERT(ueq_fifo_is_empty(&cb));
    UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);

    /*  Write & pop test */
    for (i = 0; i < buffer_size; ++i)
    {
        /* Write one chunk */
        result = ueq_fifo_write(&cb, in, buffer_size - 1);
        UEQ_ASSERT(result);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
        UEQ_ASSERT(ueq_fifo_is_full(&cb));

        /* Pop all bytes but one */
        for (j = 0; j < buffer_size - 2; ++j)
        {
            data = ueq_fifo_pop_front(&cb);
            UEQ_ASSERT(data == j);
            UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
            UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
        }

        /* Pop the last one */
        data = ueq_fifo_pop_front(&cb);
        UEQ_ASSERT(data == buffer_size - 2);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb));
        UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
    }

    /*  Write & read test, one chunk */
    ueq_fifo_init(&cb, buffer, buffer_size);

    for (i = 0; i < buffer_size; ++i)
    {
        /* Write one chunk */
        result = ueq_fifo_write(&cb, in, buffer_size - 1);
        UEQ_ASSERT(result);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
        UEQ_ASSERT(ueq_fifo_is_full(&cb));

        /* Read one chunk */
        result = ueq_fifo_read(&cb, out, buffer_size - 1);
        UEQ_ASSERT(result);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb));
        UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
        UEQ_ASSERT_SAME_DATA(in, out, buffer_size - 1);

        /* Start and end pointers have been moved, so repeat test */
    }

    /*  Write & read test, 2 chunks */
    ueq_fifo_init(&cb, buffer, buffer_size);

    for (i = 0; i < buffer_size; ++i)
    {
        /* Write first chunk */
        result = ueq_fifo_write(&cb, in, 3);
        UEQ_ASSERT(result);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
        UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);

        /* Write second chunk */
        result = ueq_fifo_write(&cb, in + 3, 2);
        UEQ_ASSERT(result);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
        UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);

        /* Read one chunk */
        result = ueq_fifo_read(&cb, out, 5);
        UEQ_ASSERT(result);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb));
        UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);
        UEQ_ASSERT_SAME_DATA(in, out, buffer_size - 1);

        /* Start and end pointers have been moved, so repeat test */
    }

    /*  Write fail test - try to write more than the buffer can hold */
    ueq_fifo_init(&cb, buffer, buffer_size);

    for (i = 0; i < buffer_size; ++i)
    {
        /* The real test */
        result = ueq_fifo_write(&cb, in, buffer_size - 1 + 1);
        UEQ_ASSERT(result == FALSE);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb));
        UEQ_ASSERT(ueq_fifo_is_full(&cb) == FALSE);

        /* Move the start & end pointers forward */
        ueq_fifo_push_back(&cb, 0);
        ueq_fifo_pop_front(&cb);
    }

    /*  Read fail test - try to read more than the buffer can hold */
    ueq_fifo_init(&cb, buffer, buffer_size);

    for (i = 0; i < buffer_size; ++i)
    {
        /* Fill it in */
        result = ueq_fifo_write(&cb, in, buffer_size - 1);
        UEQ_ASSERT(result);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
        UEQ_ASSERT(ueq_fifo_is_full(&cb));

        /* The real test here */
        result = ueq_fifo_read(&cb, in, buffer_size - 1 + 1);
        UEQ_ASSERT(result == FALSE);
        UEQ_ASSERT(ueq_fifo_is_empty(&cb) == FALSE);
        UEQ_ASSERT(ueq_fifo_is_full(&cb));

        /* Clear the buffer, then move the start & end pointers forward */
        ueq_fifo_init(&cb, buffer, buffer_size);
        ueq_fifo_push_back(&cb, 0);
        ueq_fifo_pop_front(&cb);
    }
}
